<template>
  <component class="custom-select-panel"
    :is="getComponent"
    :value="bindValue"
    :style="{height: height}"
    @input="onSelectChange"
  >
    <CustomList ref="list"
      :height="height"
      :loadData="loadTableData"
    >
      <van-cell slot-scope="scope">
        <template #title>
          <component class="select-item"
            :is="getCheckComponent"
            :shape="multiple ? 'square' : 'round'"
            icon-size="16px"
            :checked-color="color"
            :name="scope.data[finalProps.value]"
            :disabled="calcItemDisabled(scope.data)"
          >
            {{ scope.data[finalProps.text] }}
          </component>
        </template>
      </van-cell>
    </CustomList>
  </component>
</template>

<script>
import { findItemFromList } from '../../utils';
import CustomList from '../CustomList.vue';

const DEFAULT_PROPS = {
  text: 'name',
  value: 'id',
  disabled: undefined,
  pageSize: 20
};

export default {
  name: 'customListPanel',
  props: {
    // 绑定数据
    value: {
      type: [Number, String, Array]
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 是否多选
    multiple: {
      type: Boolean,
      default: false
    },
    // 选中颜色
    color: {
      type: String
    },
    // 组件高度
    height: {
      type: String
    },
    // 列表数据
    dataList: {
      type: [Array, Function],
      default: () => []
    },
    props: {
      type: Object,
      default: () => {
        return {
          ...DEFAULT_PROPS
        }
      }
    },
    // 过滤函数，仅当dataList为数组的时候生效，如果dataList是函数，请在函数中添加过滤条件
    filter: {
      type: Function
    }
  },
  components: {
    CustomList
  },
  data () {
    return {
      finalDataList: []
    }
  },
  methods: {
    // 获取列表数据
    loadTableData (pageNum) {
      return new Promise((resolve, reject) => {
        if (typeof this.dataList === 'function') {
          // dataList是一个函数，通过函数获取
          this.dataList(pageNum).then(res => {
            resolve(res);
          }).catch(e => {
            reject(e);
          });
        } else {
          // 分页获取
          let totalCount = 0;
          let tempList = [];
          if (Array.isArray(this.finalDataList)) {
            totalCount = this.finalDataList.length;
            let start = (pageNum - 1) * this.finalProps.pageSize;
            let end = start + this.finalProps.pageSize;
            tempList = this.finalDataList.slice(start, end);
          }
          resolve({
            dataList: tempList,
            totalCount: totalCount
          });
        }
      });
    },
    onSelectChange (val) {
      this.$emit('input', val);
    },
    // 获取全部数据
    getDataList () {
      if (Array.isArray(this.dataList)) return this.dataList;
      if (this.$refs.list) return this.$refs.list.getDataList();
      return [];
    },
    // 获取选中数据，仅当dataList为数组时候生效
    getSelectDataList () {
      if (!Array.isArray(this.dataList)) {
        console.error('getSelectDataList 仅在dataList为数组时生效！');
        return [];
      }
      return findItemFromList(this.dataList, this.value, this.finalProps.value);
    },
    // 获取过滤后的数据列表
    getFinalDataList () {
      if (typeof this.filter !== 'function') return this.dataList;
      return this.dataList.filter(item => {
        return this.filter(item);
      });
    },
    // 选项是否禁用
    calcItemDisabled (data) {
      if (this.disabled) return true;
      if (data == null) return false;
      if (typeof this.finalProps.disabled === 'function') {
        return this.finalProps.disabled(data);
      } else {
        return this.finalProps.disabled == null ? false : data[this.finalProps.disabled];
      }
    },
    reset () {
      this.finalDataList = this.getFinalDataList();
      if (this.$refs.list) this.$refs.list.reset();
    }
  },
  computed: {
    finalProps () {
      return {
        ...DEFAULT_PROPS,
        ...this.props
      }
    },
    getComponent () {
      return this.multiple ? 'van-checkbox-group' : 'van-radio-group';
    },
    getCheckComponent () {
      return this.multiple ? 'van-checkbox' : 'van-radio';
    },
    bindValue () {
      if (this.value == null || this.value === '') return undefined;
      if (this.multiple && !Array.isArray(this.value)) {
        return [this.value];
      }
      if (!this.multiple && Array.isArray(this.value)) {
        return this.value[0];
      }
      return this.value;
    }
  },
  watch: {
    dataList: {
      handler () {
        this.reset();
      },
      immediate: true
    }
  }
}
</script>

<style scoped>
  .custom-select-panel /deep/ .van-cell__title {
    width: 100%;
  }
</style>
